package com.teamblueplus.comicmaker;

import java.io.IOException;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.*;
import android.graphics.AvoidXfermode.Mode;
import android.media.ExifInterface;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import com.teamblueplus.R;
import com.teamblueplus.brush.CommandManager;
import com.teamblueplus.brush.DrawingPath;
import com.teamblueplus.brush.PaintBrush;

/**
 * SurfaceView for draw and crop on selected image
 * 
 * @author qui
 * 
 */
public class ImageEditorSurfaceView extends SurfaceView implements
		SurfaceHolder.Callback {
	private Boolean _run;
	protected DrawThread thread;
	private Bitmap mBitmap;
	public boolean isDrawing = true;
	// delete later
	// public DrawingPath previewPath;

	public Bitmap _objectBitmap;

	private CommandManager commandManager;

	public PaintBrush brush2;

	private int sviewWidth, sviewHeight, bottomPadding, topPadding;
	private String imagePath;
	// use when image came from gallery, cause the image is displayed
	// horizontally
	static private boolean rotateImage;
	private int origImageWidth, origImageHeight;

	// use when crop is used
	public Bitmap _croppedBitmap;
	public boolean isCropped = false;

	public ImageEditorSurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);

		// set the bottom padding to 20px
		bottomPadding = 20;

		getHolder().addCallback(this);

		// WindowManager wm = (WindowManager)
		// context.getSystemService(Context.WINDOW_SERVICE);
		// Display display = wm.getDefaultDisplay();
		// testWidth = display.getWidth();
		// testHeight = display.getHeight();

		commandManager = new CommandManager();

		brush2 = new PaintBrush();

		thread = new DrawThread(getHolder());

	}

	private Handler previewDoneHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			Log.d("draw", "handleMessage is Drawing FALSE");
			// isDrawing = false;
		}
	};

	class DrawThread extends Thread {
		private SurfaceHolder mSurfaceHolder;

		public DrawThread(SurfaceHolder surfaceHolder) {
			mSurfaceHolder = surfaceHolder;

		}

		public void setRunning(boolean run) {
			_run = run;

		}

		@Override
		public void run() {
			Canvas canvas = null;
			while (_run) {

				try {
					this.sleep(20);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				if (isDrawing == true) {
					try {

						canvas = mSurfaceHolder.lockCanvas(null);

						if (mBitmap == null) {
							mBitmap = Bitmap.createBitmap(1, 1,
									Bitmap.Config.ARGB_8888);
						}

						// we created another canvas with bitmap as parameter so
						// the canvas
						// will be draw into the bitmap, the bitmap will be use
						// to save all
						// the drawings when we save it to a file.
						final Canvas c = new Canvas(mBitmap);

						// draw black background
						c.drawColor(Color.BLACK);

						// draw the image
						c.drawBitmap(_objectBitmap, 0, topPadding, null);

						// brush2
						brush2.executeAll(c, previewDoneHandler);
						// draw the preview path
						c.drawPath(brush2.currentDrawingPath.path,
								brush2.currentDrawingPath.paint);

						// c.drawColor(0, PorterDuff.Mode.CLEAR);

						// drawing all the paths from the list
						// commandManager.executeAll(c,previewDoneHandler);

						// delete later
						// drawing a preview of the path, this is the dynamic
						// drawing
						// previewPath.draw(c);

						// this canvas just display the bitmaps on the screen
						// Rect grct = new Rect(0, 0, 200, 200);
						canvas.drawBitmap(mBitmap, 0, 0, null);

					} finally {
						mSurfaceHolder.unlockCanvasAndPost(canvas);
						// isDrawing = false;
					}

				}
			}
		}
	}

	public void addDrawingPath(DrawingPath drawingPath) {
		commandManager.addCommand(drawingPath);
	}

	public boolean hasMoreRedo() {
		return commandManager.hasMoreRedo();
	}

	public void redo() {
		isDrawing = true;
		commandManager.redo();

	}

	public void undo() {
		isDrawing = true;
		commandManager.undo();
	}

	public boolean hasMoreUndo() {
		return commandManager.hasMoreUndo();
	}

	public Bitmap getBitmap() {
		Bitmap compressBitmap = Bitmap.createScaledBitmap(mBitmap,
				this.origImageWidth, this.origImageHeight, false);
		return compressBitmap;
	}

	public void pause() {

	}

	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub
		mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
		;
		Log.d("draw", "surfaceChanged");
		Log.d("draw", "width::" + width);
		Log.d("draw", "height::" + height);

		sviewHeight = height;
		sviewWidth = width;

		this.origImageWidth = _objectBitmap.getWidth();
		this.origImageHeight = _objectBitmap.getHeight();

		_objectBitmap = Bitmap.createScaledBitmap(_objectBitmap, sviewWidth,
				sviewHeight, false);
	}

	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		Log.d("h2", "imagePathINSurfaceChange::" + imagePath);

		// if image is cropped
		if (!isCropped) {
			Log.d("h2", "surfaceCreate::NotCrop");
			_objectBitmap = ImageEditorSurfaceView.decodeSampledBitmapFromFile(
					imagePath, 480, 270);
		} else {
			_objectBitmap = _croppedBitmap;
			Log.d("h2", "surfaceCreate::Cropped");
		}
		thread = new DrawThread(getHolder());

		isDrawing = true;
		thread.setRunning(true);
		thread.start();
		Log.d("draw", "surfaceCreated");

	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		Log.d("draw", "surfaceDestroyed");

		this.isDrawing = false;
		this.thread.setRunning(false);
		boolean retry = true;
		while (retry) {
			try {
				thread.join();
				retry = false;
			} catch (InterruptedException e) {
				Log.v("pause()", e.toString());
			}
			break;
		}

		this.thread.mSurfaceHolder = null;
		this.thread = null;
		this.mBitmap = null;
		this._croppedBitmap = null;
		this._objectBitmap = null;

	}

	public static int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth, int reqHeight) {
		// Raw height and width of image
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;

		if (height > reqHeight || width > reqWidth) {
			if (width > height) {
				inSampleSize = Math.round((float) height / (float) reqHeight);
			} else {
				inSampleSize = Math.round((float) width / (float) reqWidth);
			}
		}
		return inSampleSize;
	}

	public static Bitmap decodeSampledBitmapFromFile(String path, int reqWidth,
			int reqHeight) {

		// First decode with inJustDecodeBounds=true to check dimensions
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, options);

		// Calculate inSampleSize
		options.inSampleSize = calculateInSampleSize(options, reqWidth,
				reqHeight);

		// Decode bitmap with inSampleSize set
		options.inJustDecodeBounds = false;

		Bitmap temp = BitmapFactory.decodeFile(path, options);

		// check orientation of image
		int orientation = 0;
		try {
			ExifInterface exif = new ExifInterface(path);
			orientation = exif
					.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
		} catch (IOException e) {
			e.printStackTrace();
		}

		Log.d("h2", "orientation::" + orientation);

		if (ImageEditorSurfaceView.rotateImage && orientation == 6) {

			final Matrix matrix = new Matrix();
			matrix.postRotate(90);
			Bitmap temp2 = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(),
					temp.getHeight(), matrix, true);
			return temp2;

		} else if (ImageEditorSurfaceView.rotateImage && orientation == 3) {

			final Matrix matrix = new Matrix();
			matrix.postRotate(180);
			Bitmap temp2 = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(),
					temp.getHeight(), matrix, true);
			return temp2;

		} else if (ImageEditorSurfaceView.rotateImage && orientation == 8) {

			final Matrix matrix = new Matrix();
			matrix.postRotate(270);
			Bitmap temp2 = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(),
					temp.getHeight(), matrix, true);
			return temp2;

		} else
			return temp;
	}

	public int getPageWidth() {
		return this.sviewWidth;
	}

	public int getPageHeight() {
		return this.sviewHeight - this.bottomPadding;
	}

	public int getTopPadding() {
		return this.topPadding;
	}

	public void setImagePath(String path, boolean rotate) {
		this.imagePath = path;
		rotateImage = rotate;
	}

	public int getOrigImageWidth() {
		return this.origImageWidth;
	}

	public int getOrigImageHeight() {
		return this.origImageHeight;
	}

}
